package org.example.stockdemo.job;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.example.stockdemo.entity.StockDetail;
import org.example.stockdemo.entity.StockMonitor;
import org.example.stockdemo.entity.StockRank;
import org.example.stockdemo.service.StockDetailService;
import org.example.stockdemo.service.StockMonitorService;
import org.example.stockdemo.service.TencentStockService;
import org.example.stockdemo.util.CacheUtil;
import org.example.stockdemo.util.StockUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalTime;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author :Mr.zhou
 * @description: 定时刷新股票数据任务
 * @create date: 2025/10/24 22:43
 */
@Slf4j
@Service
public class StockMinorJob {

    @Autowired
    private TencentStockService tencentStockService;
    @Autowired
    private StockDetailService stockDetailService;
    @Autowired
    private StockMonitorService stockMonitorService;


    /**
     * 上午监视
     */
    @Scheduled(cron = "0/50 * 9-11 * * ?")
    public void amStockMonitor() {
        if (!StockUtil.isTradingTime()) {
            return;
        }
        // 执行监控任务
        executeMonitorTask();

        // 保存实时股票数据
        saveStockData();
    }

    /**
     * 下午监视
     * 13:30-23:30 每30秒执行一次
     */
    @Scheduled(cron = "0/50 * 13-23 * * ?")
    public void pmStockMonitor() {
        if (!StockUtil.isTradingTime()) {
            return;
        }
        // 执行监控任务
        executeMonitorTask();

        // 保存实时股票数据
        saveStockData();
    }


    /**
     * 监视任务
     */
    private void executeMonitorTask() {
        List<StockMonitor> monitorList = stockMonitorService.list();
        if (CollectionUtils.isNotEmpty(monitorList)) {
            for (StockMonitor stockMonitor : monitorList) {
                // 获取实时数据
                StockDetail stockDetail = CacheUtil.stockCodesRealDetail.get(stockMonitor.getCode());
                if (stockDetail == null) {
                    continue;
                } else {
                    stockMonitor.setPrice(stockDetail.getPrice());
                    stockMonitor.setChangePercent(stockDetail.getChangePercent());
                    stockMonitor.setStartPrice(stockDetail.getStartPrice());
                    stockMonitor.setStartChangePercent(stockDetail.getChangePercent());
                    if (stockMonitor.getTodayLowPrice() == null) {
                        stockMonitor.setTodayLowPrice(stockDetail.getPrice());
                    } else {
                        stockMonitor.setTodayLowPrice(Math.min(stockMonitor.getTodayLowPrice(), stockDetail.getPrice()));
                    }
                    if (stockMonitor.getTodayHighPrice() == null) {
                        stockMonitor.setTodayHighPrice(stockDetail.getPrice());
                    } else {
                        stockMonitor.setTodayHighPrice(Math.max(stockMonitor.getTodayHighPrice(), stockDetail.getPrice()));
                    }

                    // 判断更新时间是否与当前时间是同一天, 如果不是这填充今日监控所需价格
                    /*if (!stockMonitor.getUpdatedAt().toLocalDate().equals(LocalDate.now())) {
                        StockMonitorDTO stockMonitorDTO=new StockMonitorDTO();
                        stockMonitorDTO.setCode(stockMonitor.getCode());
                        stockMonitorDTO.setCostPrice(stockMonitor.getCostPrice());
                        stockMonitorDTO.setMonitorPrice(stockMonitor.getMonitorPrice());
                        StockMonitor fillStockMonitor = stockMonitorService.fillPrice(stockMonitorDTO);
                        // 写入开盘价，开盘涨幅
                        stockMonitor.setStartPrice(fillStockMonitor.getStartPrice());
                        stockMonitor.setStartChangePercent(fillStockMonitor.getStartChangePercent());
                        stockMonitor.setFiveDayPrice(fillStockMonitor.getFiveDayPrice());
                        stockMonitor.setTenDayPrice(fillStockMonitor.getTenDayPrice());
                        stockMonitor.setYesterdayPrice(fillStockMonitor.getYesterdayPrice());
                    }*/
                    // 计算分时价格，成交额/成交量*0.9925 然后四舍五入保留2位小数
                    if (stockDetail.getAmount() != null && stockDetail.getVolume() != null && stockDetail.getVolume() != 0) {
                        double minutePrice = stockDetail.getAmount() / stockDetail.getVolume() * 0.9925;
                        // 四舍五入保留两位小数
                        BigDecimal bd = new BigDecimal(minutePrice).setScale(2, BigDecimal.ROUND_HALF_UP);
                        stockMonitor.setMinutePrice(bd.doubleValue());
                    }
                    // 监控开盘前25分钟
                    stockFixedMonitor(stockMonitor);
                    // 缓存
                    CacheUtil.stockMonitorCache.put(stockMonitor.getCode(), stockMonitor);
                    // 更新
                    stockMonitorService.updateById(stockMonitor);
                }

            }
        }
    }

    /**
     * 固定监控
     *
     * @param stockMonitor
     */
    private void stockFixedMonitor(StockMonitor stockMonitor) {
        LocalTime currentTime = LocalTime.now();
        StringBuffer remark = new StringBuffer();
        Double startPrice = stockMonitor.getStartPrice();
        Double price = stockMonitor.getPrice();
        double moneyVal;
        // 9点半钟执行一次

        if (currentTime.getHour() == 9 && currentTime.getMinute() == 30) {
            remark.append("今日开盘情况：");
            // 低开情况
            if (startPrice < stockMonitor.getYesterdayPrice()) {
                if (startPrice - stockMonitor.getYesterdayPrice() >= 3) {
                    remark.append("危险（S）警告：低开；").append(stockMonitor.getStartChangePercent());
                } else {
                    remark.append("警告：低开").append(stockMonitor.getStartChangePercent());
                }
            }
            // 高开情况
            if (startPrice > stockMonitor.getYesterdayPrice()) {
                if (startPrice - stockMonitor.getYesterdayPrice() >= 3) {
                    remark.append(" 快乐（S）警告：高开；").append(stockMonitor.getStartChangePercent());
                } else {
                    remark.append(" 正常：高开；").append(stockMonitor.getStartChangePercent());
                }
            }

            // 计算浮动盈亏
            moneyVal = price - stockMonitor.getCostPrice() / stockMonitor.getCostPrice() * 100;
            remark.append(" 浮动盈亏：").append(moneyVal);

        } else if (currentTime.getHour() == 9 && (currentTime.getMinute() == 35 || currentTime.getMinute() == 40) || currentTime.getMinute() == 45 || currentTime.getMinute() == 50) {
            if (currentTime.getMinute() == 35) {
                remark.append("今日开盘5分钟情况：");
            } else if (currentTime.getMinute() == 40) {
                remark.append("今日开盘10分钟情况：");
            } else if (currentTime.getMinute() == 45) {
                remark.append("今日开盘15分钟情况：");
            } else if (currentTime.getMinute() == 50) {
                remark.append("今日开盘20分钟情况：");
            } else if (currentTime.getMinute() == 55) {
                remark.append("今日开盘25分钟情况：");
            }

            // 对比分时价格
            if (stockMonitor.getMinutePrice() > price) {
                remark.append(" ↓↓↓ 跌破分时价格").append(stockMonitor.getChangePercent());
            } else {
                remark.append(" ↗↗↗ 分时以上").append(stockMonitor.getChangePercent());
            }
        }
        stockMonitor.setRemark(stockMonitor.getRemark() + " ; " + remark);
    }

    /**
     * 保存缓存股票数据
     */
    public void saveStockData() {
        ConcurrentHashMap<Long, List<StockDetail>> stockRealtimeMap = CacheUtil.groupStockCache;
        if (stockRealtimeMap.isEmpty() || !CacheUtil.isFlush)
            return;
        Collection<List<StockDetail>> lists = stockRealtimeMap.values();
        List<StockDetail> detailList = lists.stream().flatMap(Collection::stream).toList();
        // 缓存股票code-股票对象
        Map<String, StockDetail> realDetailMap = detailList.stream().collect(Collectors.toMap(StockDetail::getCode, Function.identity()));
        CacheUtil.stockCodesRealDetail.putAll(realDetailMap);

        // 监控是否异动
        priceDance(realDetailMap,0.7);
        // 批量保存到表
        stockDetailService.batchSaveStock(detailList);
    }

    /**
     * 价格异动
     */
    private void priceDance(Map<String, StockDetail> realDetailMap,double changePoint) {
        ConcurrentHashMap<String, StockDetail> oldRealDetail = CacheUtil.stockCodesRealDetail;
        if (oldRealDetail.isEmpty()) {
            return;
        }
        Collection<StockDetail> stockDetails = realDetailMap.values();
        for (StockDetail stockDetail : stockDetails) {
            String code = stockDetail.getCode();
            String name = stockDetail.getName();
            StockDetail oldStockDetail = oldRealDetail.get(code);
            if (oldStockDetail != null) {
                // 与上一次记录的百分比进行比较，判断是否有价格异动
                Double changePercent = stockDetail.getChangePercent();
                Double oldChangePercent = oldStockDetail.getChangePercent();
                Double price = stockDetail.getPrice();
                Double oldPrice = oldStockDetail.getPrice();
                if (changePercent > 0 && oldChangePercent > 0) {
                    // 0轴上方
                    double cpv = Math.abs(changePercent - oldChangePercent);
                    if (changePercent > oldChangePercent && cpv > changePoint) {
                        System.out.println("↑↑↑飞升 " + name + "[" + oldChangePercent + "——>" + changePercent + "%]");
                    }
                    if (changePercent < oldChangePercent && cpv > changePoint) {
                        System.out.println("↓↓↓猛锤 " + name + "[" + oldChangePercent + "——>" + changePercent + "%]");
                    }
                } else if (changePercent < 0 && oldChangePercent < 0) {
                    // 0轴下方
                    double cpv = Math.abs(Math.abs(changePercent) - Math.abs(oldChangePercent));
                    if (changePercent > oldChangePercent && cpv > changePoint) {
                        System.out.println("↗↗↗水下拉升 " + name + "[" + oldChangePercent + "——>" + changePercent + "%]");
                    }
                    if (changePercent < oldChangePercent && cpv > changePoint) {
                        System.out.println("↘↘↘水下摩擦 " + name + "[" + oldChangePercent + "——>" + changePercent + "%]");
                    }
                } else if (changePercent > 0 && oldChangePercent < 0) {
                    // 突破0轴
                    double cpv = Math.abs(changePercent + Math.abs(oldChangePercent));
                    if (cpv > changePoint) {
                        System.out.println("↗↗↑↑拉上水 " + name + "[" + oldChangePercent + "——>" + changePercent + "%]");
                    }
                } else {
                    // 跌破0轴
                    double cpv = Math.abs(changePercent + Math.abs(oldChangePercent));
                    if (cpv > changePoint) {
                        System.out.println("↘↘↓↓摁倒水下 " + name + "[" + oldChangePercent + "——>" + changePercent + "%]");
                    }
                }

                // 处理重点监控股票
                StockMonitor stockMonitor = CacheUtil.stockMonitorCache.get(code);
                if (stockMonitor != null) {
                    // 监视价格比较
                    StringBuffer remark = new StringBuffer();
                    double moneyVal = Math.abs(stockMonitor.getMonitorPrice() - price);
                    if (moneyVal < 0.2) {
                        remark.append(" **接近监视价格**");
                    }

                    // 5日线价格比较
                    if (stockMonitor.getFiveDayPrice() > price && oldPrice < stockMonitor.getFiveDayPrice()) {
                        remark.append(" 跌破5日线");
                    } else if (stockMonitor.getFiveDayPrice() < price && oldPrice > stockMonitor.getFiveDayPrice()) {
                        remark.append(" 突破5日线");
                    }

                    // 10日线价格比较
                    if (stockMonitor.getTenDayPrice() > price && oldPrice < stockMonitor.getTenDayPrice()) {
                        remark.append(" 跌破10日线");
                    } else if (stockMonitor.getTenDayPrice() < price && oldPrice > stockMonitor.getTenDayPrice()) {
                        remark.append(" 突破10日线");
                    }
                    stockMonitor.setRemark(stockMonitor.getRemark() + " ; " + remark);
                    CacheUtil.stockMonitorCache.put(code, stockMonitor);
                }
            }
        }

    }

    private void printStockRank(List<StockRank> stockRankList) {
        for (StockRank stockDetail : stockRankList) {
            System.out.println(stockDetail.getName() + "(" + stockDetail.getCode() + ") " + stockDetail.getPrice() + " " +
                    stockDetail.getChangePercent() + " " + stockDetail.getMainNetIn());
        }
    }


}